programming4us
           
 
 
Programming

Parallel Programming with Microsoft Visual Studio 2010 : Task Parallelism - Unhandled Exceptions in Tasks

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
8/11/2011 11:42:22 AM
Tasks are not immune to exceptions. An unhandled exception raised in a task is handled differently by the common language runtime (CLR) than a typical exception. Unhandled exceptions in tasks are not handled in the context of the task, but in the context of the joining thread. Essentially, unhandled exceptions in a task are deferred and propagated to the joining thread. The joining thread can then observe the exception as the observer.

The unhandled exception propagated to the observer is wrapped in an AggregateException object. If you’re waiting on multiple tasks, the AggregateException might aggregate more than one unhandled exception from different parallel tasks. If a single exception is raised, the InnerException property of the AggregateException contains the original exception. For multiple exceptions, the InnerExceptions property returns a collection of Exception objects—one for each unhandled exception.

There are many ways to observe an unhandled exception raised in a task. Waiting for the task will observe the exception: Wait, WaitAll, or WaitAny methods. The joining thread then becomes the observer and is responsible for handling the exception. If the Wait method is within the scope of a try block (protected code), the otherwise unhandled exception of a task can be caught. You can then unbundle the AggregateException object and examine the original exception(s) in the InnerException or InnerExceptions property.

Remember that Parallel.Invoke ends with an implicit Task.WaitAll. This blocks the joining thread until all the tasks have completed. When Parallel.Invoke returns, any unhandled exceptions are observed, and if the code is running within a try block, you can handle the exception(s) in a catch block.

After scheduling a task, the TPL tracks the status of that task. The status is exposed as the Task.Status property, which is a TaskStatus type. TaskStatus is an enumeration. Some of the possible values are TaskStatus.WaitingToRun, TaskStatus.Running, TaskStatus.RanToCompletion, and TaskStatus.Canceled, which are self-explanatory. When a task raises an unhandled exception, the task status is TaskStatus.Faulted.

The following image shows a sequence diagram of a task that throws an exception. The exception is observed in a try block and caught in the subsequent catch block. Thicker vertical lines represent tasks executing on a thread.

Here are the steps in the sequence diagram.

  • Within a try block, invoke TaskA and TaskB. TaskB has the longer duration.

  • TaskA throws a divide-by-zero exception, which is wrapped in an AggregateException.

  • When TaskB completes, the WaitAll observes the unhandled exception raised by TaskA.

  • The catch block retrieves the original exception as the InnerException.

Note that unhandled exceptions must be observed before the related task is garbage-collected; otherwise, the unhandled exception might crash the application. Here’s an example of successfully handling an unhandled exception in a parallel task.

Create a task that throws an unhandled exception that is observed with a Task.Wait method

  1. Create a console application. In the Main function, create a task reference, which is set to null.

    Task TaskA = null;

  2. Start a try/catch block. You will enter code guarded for an exception in the try block.

    try {

  3. In the try block, you will create and start a new task. Initialize the task with a lambda expression. In the lambda expression, define two integer variables. Set one of the integers to zero. Divide by the integer variable that has the zero value to raise the divide-by-zero exception.

    TaskA = Task.Factory.StartNew(() => {
    int a = 5, b = 0;
    a /= b;});

  4. Wait for the task to complete.

    TaskA.Wait(); }

  5. In the catch statement, catch the AggregateException exception. This will catch and observe the unhandled exception from the task.

    catch(AggregateException ae) {

  6. In the catch block, display the task status and inner exception, which contains the original exception.

  7. Build and run the application.

Here is the complete application.

class Program
{
static void Main(string[] args)
{
Task TaskA = null;
try {
TaskA = Task.Factory.StartNew(() => {
int a = 5, b = 0;
a /= b;
});
TaskA.Wait();
}
catch(AggregateException ae) {
Console.WriteLine("Task has "+TaskA.Status.ToString());
Console.WriteLine(ae.InnerException);
}
}
}

Observe and iterate unhandled exceptions from three separate tasks

Different from the previous example, this walkthrough lists the separate exceptions thrown from different tasks.

  1. Create a console application. Before the Main function, define MethodA, MethodB, and MethodC methods. Each method throws an explicit exception. In the exception constructor, provide the name of the task.

    static void MethodA() { throw new Exception("TaskA Exception"); }
    static void MethodB() { throw new Exception("TaskB Exception"); }
    static void MethodC() { throw new Exception("TaskC Exception"); }

  2. Start a try/catch block. You will enter code guarded for an exception in the try block.

    try {

  3. In the try block, create and start three tasks. Each task is initialized with a different method.

    var TaskA=Task.Factory.StartNew(MethodA);
    var TaskB=Task.Factory.StartNew(MethodB);
    var TaskC=Task.Factory.StartNew(MethodC);

  4. Use the Task.WaitAll method so that you can wait for the tasks and observe any exception.

    Task.WaitAll(new Task[] {TaskA, TaskB, TaskC}); }

  5. In the catch statement, catch the AggregateException exception. This will catch all unhandled exceptions of the tasks.

    catch (AggregateException ae) {

  6. In the catch block, iterate the AggregateException.InnerExceptions property and display each individual exception.

  7. Build and run the application.

Here is the complete application.

class Program
{
static void MethodA() { throw new Exception("TaskA Exception"); }
static void MethodB() { throw new Exception("TaskB Exception"); }
static void MethodC() { throw new Exception("TaskC Exception"); }
static void Main(string[] args)
{
try {
var TaskA=Task.Factory.StartNew(MethodA);
var TaskB=Task.Factory.StartNew(MethodB);
var TaskC=Task.Factory.StartNew(MethodC);
Task.WaitAll(new Task[] {TaskA, TaskB, TaskC});
}
catch (AggregateException ae) {
foreach (var ex in ae.InnerExceptions) {
Console.WriteLine(ex.Message);
}
}
}
}

The following code is similar to the previous example, except that it calls Parallel.Invoke instead of TaskFactory.StartNew.

try {
Parallel.Invoke(new Action[] { MethodA, MethodB, MethodC });
}
catch (AggregateException ae){
foreach (var ex in ae.InnerExceptions) {
Console.WriteLine(ex.Message);
}
}

The previous examples use a foreach loop to inspect and handle unhandled exceptions from different tasks. Alternatively, you can call the AggregateException.Handle method, which takes a callback function (delegate) as its only parameter. The delegate accepts the original exception as the single parameter and returns a Boolean: Task<TResult>. The return value indicates whether the unhandled exception was handled. Return true when you successfully handle the exception, otherwise return false. If you return false, the exception will continue to propagate up the call stack as a new aggregate exception. This new AggregateException will contain all the exceptions where the handler delegate returned false.

AggregateException calls the provided callback method for the exception from a task. For example, if there are four unhandled exceptions, it calls the callback four times. You’ll practice handling exceptions with a callback in the next exercise.

Handle task exceptions with a callback function

  1. Create a console application. Before the Main function, define MethodA, MethodB, and MethodC methods. Each method throws an explicit exception. In the exception constructor, provide the name of the task.

    static void MethodA() { throw new Exception("TaskA Exception"); }
    static void MethodB() { throw new Exception("TaskB Exception"); }
    static void MethodC() { throw new Exception("TaskC Exception"); }

  2. Start a try/catch block for handling exceptions.

    try {

  3. In the try block, execute the three methods as tasks by using the Parallel.Invoke method.

    Parallel.Invoke(new Action[] { MethodA, MethodB, MethodC }); }

  4. In the catch statement, catch the AggregateException exception. This will catch all unhandled exceptions of the tasks.

    catch (AggregateException ae) {

  5. Call the Handle method on the AggregateException object. Enter the callback as a lambda expression.

    ae.Handle(ex => {

  6. In the lambda expression, display the current exception message. Return true to indicate that the exception was handled.

  7. Build and run the application.

Here is the complete application.

class Program
{
static void MethodA() { throw new Exception("TaskA Exception"); }
static void MethodB() { throw new Exception("TaskB Exception"); }
static void MethodC() { throw new Exception("TaskC Exception"); }
static void Main(string[] args)
{
try
{
Parallel.Invoke(new Action[] { MethodA, MethodB, MethodC });
}
catch (AggregateException ae)
{
ae.Handle(ex =>
{
Console.WriteLine(ex.Message);
return true;
});
}
}
}

As mentioned previously, a task can return a value, which you can inspect by using the Task<TResult>.Result property. If the Task has not completed, the current thread is suspended until the task finishes and returns a value. In addition, the Task<TResult>.Result property will observe an unhandled exception of the task, if any. Here is an example.

try{
var TaskA=Task<int>.Factory.StartNew(() =>{
throw new DivideByZeroException();
return 42;
});

// Unhandled exception observed.
Console.WriteLine(TaskA.Result);
}
catch (AggregateException ae) {
// handle exception
Console.WriteLine(ae.InnerException.Message);
}
Other -----------------
- Parallel Programming with Microsoft Visual Studio 2010 : Introduction to Parallel Tasks
- jQuery 1.3 : DOM Manipulation - Moving elements
- .NET Debugging : Introduction to the Tools - .NET 2.0—Redistributable & .NET 2.0—SDK
- .NET Debugging : Managed Heap and Garbage Collection
- Context and Interception : Custom Component Services (part 3) - The Transaction Management Service
- Context and Interception : Custom Component Services (part 2) - The Logbook Service
- Context and Interception : Custom Component Services (part 1) - Building a Custom Context Attribute & Installing a Custom Message Sink
- Software Testing with Visual Studio Team System 2008 : Data-driven unit testing
- Software Testing with Visual Studio Team System 2008 : Unit testing an ASP.NET application
- Microsoft Enterprise Library : Error Management Made Exceptionally Easy - Replacing an Exception & Logging an Exception
- Microsoft Enterprise Library : Error Management Made Exceptionally Easy - Diving in with a Simple Example
- iPhone Programming : Connecting to the Network - Embedding a Web Browser in Your App
- iPhone Programming : Connecting to the Network - Detecting Network Status
- Parallel Programming with Microsoft Visual Studio 2010 : Introduction to Parallel Programming - Software Patterns
- Parallel Programming with Microsoft Visual Studio 2010 : Introduction to Parallel Programming - Multicore Computing & Speedup
- Microsoft ASP.NET 3.5 : Web Services for ASP.NET AJAX Applications (part 2) - Consuming AJAX Web Services
- Microsoft ASP.NET 3.5 : Web Services for ASP.NET AJAX Applications (part 1) - Remote Calls via Web Services
- Microsoft ASP.NET 3.5 : AJAX-Enabled Web Services - Implementing the AJAX Paradigm
- The Art of SEO : Measuring Search Traffic (part 2)
- The Art of SEO : Measuring Search Traffic (part 1)
 
 
 
Top 10
 
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
programming4us programming4us